---
title: 實戰專案
---

本模組提供一系列實戰專案，旨在鞏固你對 C++ 及其核心優勢的理解，尤其是在與 JavaScript 比較時。這些專案強調性能、記憶體管理和系統級程式設計，讓你能夠應用在本教程中學到的概念。

## 專案 1：高性能資料處理系統

**目標：** 建立一個命令列應用程式，高效處理大型資料集，重點關注優化的資料結構和演算法。

**應用關鍵概念：**
*   **STL 容器：** `std::vector`、`std::unordered_map` 用於高效的資料儲存和查找。
*   **STL 演算法：** `std::sort`、`std::transform`、`std::accumulate` 用於資料操作。
*   **記憶體管理：** 高效使用堆疊與堆積，最小化分配。
*   **性能優化：** 編譯器標誌、快取友好設計、潛在的多執行緒。

**情境：** 讀取一個包含數值資料的大型 CSV 檔案，執行計算（例如，每列的平均值、總和、標準差），根據條件篩選資料，並將結果寫入另一個檔案。

<UniversalEditor title="資料處理範例 (概念性)" compare={true}>
```javascript !! js
// JavaScript: 使用陣列方法處理資料
const data = [
  { id: 1, value: 10 },
  { id: 2, value: 20 },
  { id: 3, value: 15 }
];

const sum = data.reduce((acc, item) => acc + item.value, 0);
console.log("總和:", sum);

const filtered = data.filter(item => item.value > 12);
console.log("篩選後:", filtered);
```

```cpp !! cpp
// C++: 使用 STL 處理資料 (概念性)
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>

struct DataPoint {
  int id;
  double value;
};

int main() {
  std::vector<DataPoint> data = {
    {1, 10.0},
    {2, 20.0},
    {3, 15.0}
  };

  double sum = std::accumulate(data.begin(), data.end(), 0.0,
                               [](double acc, const DataPoint& dp) { return acc + dp.value; });
  // std::cout << "總和: " << sum << std::endl;

  std::vector<DataPoint> filtered;
  std::copy_if(data.begin(), data.end(), std::back_inserter(filtered),
               [](const DataPoint& dp) { return dp.value > 12.0; });
  // for (const auto& dp : filtered) {
  //   std::cout << "篩選後: " << dp.id << ", " << dp.value << std::endl;
  // }

  return 0;
}
```
</UniversalEditor>

## 專案 2：簡單遊戲引擎

**目標：** 開發一個基本的 2D 遊戲引擎或一個簡單的遊戲（例如，基於控制台的文字冒險遊戲或使用 SDL/SFML 等函式庫的簡單圖形遊戲），以了解遊戲循環、渲染和事件處理。

**應用關鍵概念：**
*   **物件導向程式設計：** 遊戲物件（玩家、敵人、物品）的類別、繼承。
*   **指標/引用：** 管理遊戲實體，可能使用智能指標進行資源管理。
*   **性能優化：** 遊戲循環效率、渲染優化。
*   **記憶體管理：** 處理遊戲資產和動態物件。

**情境：** 建立一個簡單的遊戲，其中角色在網格上移動，與物件互動，並遇到敵人。重點關注核心遊戲循環、輸入處理和基本渲染。

<UniversalEditor title="遊戲循環範例 (概念性)" compare={true}>
```javascript !! js
// JavaScript: 遊戲循環 (例如，用於瀏覽器遊戲)
let playerX = 0;
let gameRunning = true;

function update() {
  playerX += 1; // 移動玩家
  // console.log("玩家 X:", playerX);
}

function draw() {
  // console.log("在 X 處繪製玩家:", playerX);
}

function gameLoop() {
  if (gameRunning) {
    update();
    draw();
    requestAnimationFrame(gameLoop);
  }
}

// gameLoop();
```

```cpp !! cpp
// C++: 遊戲循環 (概念性)
#include <iostream>
#include <chrono>
#include <thread>

int playerX = 0;
bool gameRunning = true;

void update() {
  playerX += 1; // 移動玩家
  // std::cout << "玩家 X: " << playerX << std::endl;
}

void draw() {
  // std::cout << "在 X 處繪製玩家: " << playerX << std::endl;
}

int main() {
  // 遊戲循環
  while (gameRunning) {
    update();
    draw();

    // 模擬幀率 (例如，60 FPS)
    // std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 60));

    if (playerX > 100) { // 範例退出條件
      gameRunning = false;
    }
  }
  return 0;
}
```
</UniversalEditor>

## 專案 3：系統工具開發

**目標：** 建立一個與作業系統互動的命令列工具，演示檔案系統操作、行程管理或網路診斷。

**應用關鍵概念：**
*   **檔案 I/O：** 讀取/寫入檔案、目錄操作。
*   **系統呼叫：** 直接與作業系統互動（例如，`fork`、`exec`、`stat`）。
*   **錯誤處理：** 系統級故障的穩健錯誤報告。
*   **跨平台考量：** 如果目標是多作業系統支援。

**情境：** 建立一個工具，列出目錄中的檔案，搜尋特定檔案類型，或監控系統資源（例如，CPU 使用率、記憶體使用率）。

<UniversalEditor title="檔案列表範例 (概念性)" compare={true}>
```javascript !! js
// JavaScript (Node.js): 檔案系統操作
const fs = require('fs');

// 列出當前目錄中的檔案
fs.readdir('.', (err, files) => {
  if (err) {
    console.error("讀取目錄時發生錯誤:", err);
    return;
  }
  console.log("檔案:", files);
});
```

```cpp !! cpp
// C++: 檔案列表 (概念性 - 需要平台特定標頭)
// #include <iostream>
// #include <string>
// #include <vector>
// #include <filesystem> // C++17 for filesystem operations

// int main() {
//   // 列出當前目錄中的檔案 (C++17 filesystem)
//   // try {
//   //   for (const auto& entry : std::filesystem::directory_iterator(".")) {
//   //     std::cout << entry.path().filename() << std::endl;
//   //   }
//   // } catch (const std::filesystem::filesystem_error& e) {
//   //   std::cerr << "讀取目錄時發生錯誤: " << e.what() << std::endl;
//   // }
//   return 0;
// }
```
</UniversalEditor>

## 專案 4：網路伺服器

**目標：** 開發一個簡單的網路伺服器（例如，基本的 HTTP 伺服器或自訂 TCP 伺服器）來處理用戶端連線和資料交換。

**應用關鍵概念：**
*   **網路程式設計：** 通訊端點、TCP/UDP 協定。
*   **並發/多執行緒：** 同時處理多個用戶端連線。
*   **錯誤處理：** 穩健的網路錯誤管理。
*   **記憶體管理：** 管理網路緩衝區和用戶端資料。

**情境：** 建立一個伺服器，監聽特定埠，接受用戶端連線，從用戶端接收資料，處理資料，並將回應傳回。例如，一個簡單的聊天伺服器或鍵值儲存伺服器。

<UniversalEditor title="基本 TCP 伺服器 (概念性)" compare={true}>
```javascript !! js
// JavaScript (Node.js): TCP 伺服器
const net = require('net');

// const server = net.createServer((socket) => {
//   console.log('用戶端已連線');
//   socket.on('data', (data) => {
//     console.log('收到:', data.toString());
//     socket.write('回聲: ' + data.toString());
//   });
//   socket.on('end', () => {
//     console.log('用戶端已斷開連線');
//   });
// });

// server.listen(3000, () => {
//   console.log('TCP 伺服器正在監聽埠 3000');
// });
```

```cpp !! cpp
// C++: 基本 TCP 伺服器 (概念性 - 需要平台特定標頭)
// #include <iostream>
// #include <string>
// #include <vector>
// #include <sys/socket.h> // For socket, bind, listen, accept (Unix-like)
// #include <arpa/inet.h>  // For inet_ntoa (Unix-like)
// #include <unistd.h>   // For close (Unix-like)

// int main() {
//   // 建立通訊端點
//   int server_fd = socket(AF_INET, SOCK_STREAM, 0);
//   if (server_fd == 0) { /* std::cerr << "socket 失敗" << std::endl; */ return 1; }

//   // 綁定到埠
//   sockaddr_in address;
//   address.sin_family = AF_INET;
//   address.sin_addr.s_addr = INADDR_ANY;
//   address.sin_port = htons(3000);
//   if (bind(server_fd, (sockaddr *)&address, sizeof(address)) < 0) {
//     // std::cerr << "綁定失敗" << std::endl; return 1;
//   }

//   // 監聽連線
//   if (listen(server_fd, 3) < 0) {
//     // std::cerr << "監聽失敗" << std::endl; return 1;
//   }
//   // std::cout << "伺服器正在監聽埠 3000" << std::endl;

//   // 接受連線
//   int new_socket = accept(server_fd, (sockaddr *)&address, (socklen_t*)&address);
//   if (new_socket < 0) { /* std::cerr << "接受失敗" << std::endl; */ return 1; }
//   // std::cout << "用戶端已連線" << std::endl;

//   char buffer[1024] = {0};
//   read(new_socket, buffer, 1024);
//   // std::cout << "收到: " << buffer << std::endl;
//   std::string hello = "Hello from C++ server!";
//   send(new_socket, hello.c_str(), hello.length(), 0);
//   // std::cout << "Hello 訊息已傳送" << std::endl;

//   close(new_socket);
//   close(server_fd);
//   return 0;
// }
```
</UniversalEditor>

## 專案架構設計

對於每個專案，請考慮以下架構方面：
*   **模組化：** 將專案分解為更小、更易於管理的組件（類別、函式、檔案）。
*   **關注點分離：** 確保程式碼的不同部分處理不同的職責。
*   **設計模式：** 適當應用相關的設計模式（例如，單例、工廠、觀察者）。
*   **錯誤處理策略：** 實作一致的錯誤處理方法（例外、錯誤碼）。
*   **測試策略：** 規劃單元測試和整合測試。

## 性能優化實踐

在這些專案中，積極應用學到的性能優化技術：
*   **定期分析：** 使用分析工具識別瓶頸。
*   **選擇高效的資料結構：** 根據存取模式和性能需求選擇 STL 容器。
*   **最小化動態分配：** 優先使用堆疊分配或智能指標，並重複使用記憶體。
*   **快取感知：** 設計資料結構和存取模式以實現快取友好。
*   **並發：** 適當利用多執行緒處理可並行化的任務。

## 部署和發布

考慮部署 C++ 應用程式的步驟：
*   **編譯：** 使用適當的優化標誌編譯發布版本。
*   **依賴項：** 管理外部函式庫（例如，使用 Conan、vcpkg 等套件管理器）。
*   **跨平台建置：** 為不同的作業系統設定建置系統（例如，CMake）。
*   **打包：** 建立安裝程式或可部署的壓縮檔。

---

### 練習題：
1.  對於高性能資料處理系統專案，你將如何選擇 `std::vector` 和 `std::list` 來儲存資料，為什麼？
2.  在簡單遊戲引擎專案中，你將如何處理使用者輸入並更新遊戲狀態，使其既響應又高效？
3.  開發網路伺服器時，同時處理多個用戶端連線的關鍵考量是什麼？

### 專案構想 (進階)：
*   **自訂記憶體分配器：** 為你的其中一個專案中的特定資料結構實作自訂記憶體分配器，以更深入地控制記憶體管理並可能提高性能。
*   **基準測試工具：** 建立一個小型基準測試工具，以測量不同 C++ 演算法或資料結構之間的性能。
*   **外掛程式系統：** 為你的其中一個應用程式設計一個簡單的外掛程式系統，允許動態新增功能。
